package com.googlecode.c4e.ui.views;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.ui.part.DrillDownAdapter;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.part.WorkbenchPart;

import com.googlecode.c4e.internal.ContentProvider;
import com.googlecode.c4e.internal.IContinuumPluginListener;
import com.googlecode.c4e.model.Project;
import com.googlecode.c4e.model.RootElement;

public class ProjectsView extends ViewPart implements ISelectionListener {

  public static final String VIEW_ID = ProjectsView.class.getName();

  private RootElement root;
  private TreeViewer treeViewer;
  private DrillDownAdapter drillPart;

  private Action newProfileAction;
  private Action refreshAction;
  private ContentProvider contentProvider;

  private IContinuumPluginListener listener = new IContinuumPluginListener() {
    public void profileAdded(final RootElement root) {
      getViewer().getControl().getDisplay().syncExec(new Runnable() {
        public void run() {
          refreshViewer(null);
          getViewer().setSelection(new StructuredSelection(root));
        }
      });
    }
  };

  protected void contributeActions() {
    refreshAction = new Action("Refresh") {
      public void run() {
        System.err.println("Refreshing....");
        refreshViewer(null);
      }
    };
    refreshAction.setToolTipText("Refresh");
    // Create the popup menu
    MenuManager menuMgr = new MenuManager();
    menuMgr.add(refreshAction);
    Tree tree = treeViewer.getTree();
    Menu menu = menuMgr.createContextMenu(tree);
    menuMgr.addMenuListener(new IMenuListener() {
        public void menuAboutToShow(IMenuManager manager) {
            addWorkbenchActions(manager);
        }

    });
    menuMgr.setRemoveAllWhenShown(true);
    tree.setMenu(menu);
    getSite().registerContextMenu(menuMgr, treeViewer);
  }

  protected void addWorkbenchActions(IMenuManager manager) {
    manager.add(refreshAction);
  }

  public void createPartControl(Composite parent) {
    treeViewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
    contentProvider = new ContentProvider();
    treeViewer.setContentProvider(contentProvider);
    treeViewer.setLabelProvider(new WorkbenchLabelProvider());
    getSite().setSelectionProvider(treeViewer);
    root = new RootElement();
    treeViewer.setInput(root);
    drillPart = new DrillDownAdapter(treeViewer);

    contributeActions();

    initializeListeners();
  }

  /**
   * initialize the listeners
   */
  protected void initializeListeners() {
    getSite().getWorkbenchWindow().getSelectionService()
        .addPostSelectionListener(this);

    treeViewer.getControl().addKeyListener(new KeyAdapter() {
      public void keyPressed(KeyEvent event) {
        if (event.keyCode == SWT.F5) {
          refreshAction.run();
        }
      }
    });

    treeViewer.addDoubleClickListener(new IDoubleClickListener() {
      public void doubleClick(DoubleClickEvent e) {
        handleDoubleClick(e);
      }
    });
  }

  /**
   * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart,
   *      org.eclipse.jface.viewers.ISelection)
   */
  public void selectionChanged(IWorkbenchPart part, ISelection selection) {
    String msg = getStatusLineMessage(selection);
    getViewSite().getActionBars().getStatusLineManager().setMessage(msg);
  }

  private String getStatusLineMessage(ISelection selection) {
    if (selection == null || selection.isEmpty()
        || !(selection instanceof IStructuredSelection)) {
      return "";
    }
    IStructuredSelection s = (IStructuredSelection) selection;

    if (s.size() > 1) {
      return "";
    }
    return s.getFirstElement().toString();
  }

  /**
   * @see WorkbenchPart#setFocus
   */
  public void setFocus() {
    treeViewer.getControl().setFocus();
  }

  /**
   * Method getShell.
   *
   * @return Shell
   */
  protected Shell getShell() {
    return treeViewer.getTree().getShell();
  }

  /**
   * Returns the viewer.
   *
   * @return TreeViewer
   */
  protected TreeViewer getViewer() {
    return treeViewer;
  }

  /**
   * this is called whenever a new repository location is added for example or
   * when user wants to refresh
   */
  protected void refreshViewer(Object object) {
    if (treeViewer == null) {
      return;
    } else {
      treeViewer.refresh();
    }
  }

  private void handleDoubleClick(DoubleClickEvent e) {
    // Only act on single selection
    ISelection selection = e.getSelection();
    if (selection instanceof IStructuredSelection) {
      IStructuredSelection structured = (IStructuredSelection) selection;
      if (structured.size() == 1) {
        Object first = structured.getFirstElement();
        if (first instanceof Project) {
          // open list of builds
          // do noting at this moment
        } else {
          // Try to expand/contract
          treeViewer.setExpandedState(first, !treeViewer
              .getExpandedState(first));
        }
      }
    }
  }

  /**
   * @see org.eclipse.ui.IWorkbenchPart#dispose()
   */
  public void dispose() {
    super.dispose();
    treeViewer = null;
  }
}